1 Investigating haematopoietic progenitors from early foetal liver

In order to investigate the properties of a novel lympho-myeloid progenitor cell we isolated cells from early foetal liver

2 Transcriptional profile PCA and differential gene expression (DGA)

2.1 Sorting

Isolated cells were sorted using a variety of cell markers

2.2 RNA-seq

RNA was isolated and sequenced from the various cell types.

2.3 Sample summary

sample_table <- read.delim('charlotta_simplified_table.tsv', stringsAsFactors = FALSE)

rownames(sample_table) <- sample_table$Name
sample_table$Name <- NULL
sample_table$SampleID <- NULL
sample_table$batch <- c(rep("nov_18", 27), rep("mar_19",32))
sample_table$stage <- c("w12","w12","w10","w10","w10","CS19",
                        "CS19","CS19","CB","CB","CB","CS16",
                        "CS16","CB","CB","CB","w13","w13",
                        "CS20","CS20","CS20","w8","w8","w8",
                        "BM","BM","BM","BM","BM","BM","CS19"
                        ,"CS19","BM","BM","BM","BM","BM","BM",
                        "CB","CB","CB","CS2","CS2","CS2","CS2"
                        ,"CS2","CS2","w13","w13","w13","CS23",
                        "CS23","CS23","CS22","CS22","CS22",
                        "w13","w13","w13")

sample_table$diff_groups <- c(1,2,3,1,2,3,1,2,3,1,2,2,1,3,1,2,3,2,3,1,2,3,2,1,1,2,3,3,2,1,2,1,3,2,1,3,2,1,3,2,1,3,2,1,3,2,1,3,2,1,3,2,1,3,2,1,3,2,1)

sample_table$pools <- c("W12_13","W12_13","W8_10","W8_10","W8_10","CS19_23","CS19_23","CS19_23","CB","CB","CB","CS16","CS16","CB","CB","CB","W12_13","W12_13","CS19_23","CS19_23","CS19_23","W8_10","W8_10","W8_10","BM","BM","BM","BM","BM","BM","CS19_23","CS19_23","BM","BM","BM","BM","BM","BM","CB","CB","CB","CS19_23","CS19_23","CS19_23","CS19_23","CS19_23","CS19_23","W12_13","W12_13","W12_13","CS19_23","CS19_23","CS19_23","CS19_23","CS19_23","CS19_23","W12_13","W12_13","W12_13")

datatable(sample_table) %>% 
  formatStyle("diff_groups", backgroundColor = styleEqual(c(1,2,3), c("#EAD3BF","#AA9486", "#B6854D"))) %>%
  formatStyle("pools", backgroundColor = styleEqual(c("W12_13","CS19_23","CB","W8_10","BM","CS16"), c("#9986A5","#79402E", "#CCBA72","#F3DF6C","#D9D0D3","#8D8680")))

2.4 PCA

2.4.1 PCA ‘All’ working with FPKMS and quantile normalization

#mar_22_19_fpkms <- read.delim('myriad/22_03_19_fpkms', header = TRUE, stringsAsFactors = FALSE ) 
#nov_20_18_fpkms <- read.delim('20_nov_2018/myriad/20_nov_18_fpkms', header = TRUE, stringsAsFactors = FALSE )

mar_22_19_fpkms <- readRDS("mar_22_19_fpkms.RDS")
nov_20_18_fpkms <- readRDS("nov_20_18_fpkms.RDS")

mar_22_19_fpkms<-dplyr::rename(mar_22_19_fpkms,
                               BM_P5_11       = C23_N728_S505,
                               BM_P10_11      = B04_N704_S503,
                               BM_P12_11      = B06_N706_S503,
                               CS19_P5_11     = B08_N710_S503,
                               CS19_P12_11    = B12_N715_S503,
                               BM1_P5_12      = B14_N718_S503,
                               BM1_P10_12     = B16_N720_S503,
                               BM1_P12_12     = B18_N722_S503,
                               BM2_P5_12      = B20_N724_S503,
                               BM2_P10_12     = B22_N727_S503,
                               BM2_P12_12     = F20_N724_S508,
                               CB_P5_12       = E23_N728_S507,
                               CB_P10_12      = D04_N704_S506,
                               CB_P12_12      = D06_N706_S506,
                               CS22_P5_12     = D08_N710_S506,
                               CS22_P10_12    = D10_N712_S506,
                               CS22_P12_12    = D12_N715_S506,
                               CS20_P5_12     = D14_N718_S506,
                               CS20_P10_12    = D16_N720_S506,
                               CS20_P12_12    = D18_N722_S506,
                               FL13w_P5_13    = D20_N724_S506,
                               FL13w_P10_13   = D22_N727_S506,
                               FL13w_P12_13   = F22_N727_S508,
                               CS23_P5_13     = G23_N728_S510,
                               CS23_P10_13    = F04_N704_S508,
                               CS23_P12_13    = F06_N706_S508,
                               CS22_P5_19     = F08_N710_S508,
                               CS22_P10_19    = F10_N712_S508,
                               CS22_P12_19    = F12_N715_S508,
                               w13_FL_P5_19   = F14_N718_S508,
                               w13_FL_P10_19  = F16_N720_S508,
                               w13_FL_P12_19  = F18_N722_S508)

fpkms <- left_join(nov_20_18_fpkms,mar_22_19_fpkms, by = c("ensgene" = "ensgene" ))
fpkms <- dplyr::rename(fpkms,symbol = symbol.x)
fpkms$symbol.y <- NULL
my_rows <- apply(fpkms[,3:length(colnames(fpkms))], 1, max) >=5;
fpkms <- fpkms[my_rows,]
fpkms <- fpkms[complete.cases(fpkms),]
temp_fpkms <- fpkms[,3:61][,order(match(colnames(fpkms[,3:61]),rownames(sample_table)))]
fpkms[,3:61]<-NULL
fpkms <- cbind(fpkms,temp_fpkms)
rm(temp_fpkms)
fpkms_counts_only <- fpkms[,3:length(colnames(fpkms))]
## Log transform the data
log.data = log2(fpkms_counts_only+1)

## Quantile normalization
normalized.data = normalize.quantiles(as.matrix(log.data)) # A quantile normalization.

## Copy the row and column names from data to data2:
rownames(normalized.data) = fpkms$ensgene
colnames(normalized.data) = colnames(fpkms[,3:length(colnames(fpkms))])

## Transpose the matrix back for PCA
normalized.data = t(normalized.data)

fit <- prcomp(normalized.data)

x="PC1"
y="PC2"
x.lab = paste(x, sprintf('(%0.1f%% explained var.)', 100 * fit$sdev[which(colnames(fit$x) == x)]^2/sum(fit$sdev^2)))
y.lab = paste(y, sprintf('(%0.1f%% explained var.)', 100 * fit$sdev[which(colnames(fit$x) == y)]^2/sum(fit$sdev^2)))
data <- data.frame(fit$x)
data<-rownames_to_column(data, var = "sample")
data<-left_join(data,rownames_to_column(sample_table, var = "sample_id"), by = c("sample" = "sample_id"))

## =======================================================================
## Preliminary PCA pre-batch normaliztion
## =======================================================================
pca_plot <- function(data) {
fit <- prcomp(data)

x="PC1"
y="PC2"
x.lab = paste(x, sprintf('(%0.1f%% explained var.)', 100 * fit$sdev[which(colnames(fit$x) == x)]^2/sum(fit$sdev^2)))
y.lab = paste(y, sprintf('(%0.1f%% explained var.)', 100 * fit$sdev[which(colnames(fit$x) == y)]^2/sum(fit$sdev^2)))
data <- data.frame(fit$x)
data<-rownames_to_column(data, var = "sample")
data<-left_join(data,rownames_to_column(sample_table, var = "sample_id"), by = c("sample" = "sample_id"))


ggplot(data,aes(PC1,PC2,colour = batch,shape = Phenotype)) + 
  geom_point(size = 2) + 
  geom_label_repel(aes(label = sample),
  size = 2,
  box.padding   = 0.1, 
  point.padding = 0.1,
  segment.color = 'grey50') +
  xlab(label = x.lab) +
  ylab(label = y.lab) +
  theme_minimal()
}

pca_plot(normalized.data)

2.4.2 Why are they outliers?

Some of them have overrepresented sequences?

overrepresented

overrepresented

ggplot(data,aes(PC1,PC2,colour = batch,shape = Phenotype)) + geom_point(size = 2)  + gghighlight(sample == "CS22_P10_12" | sample == "CS22_P12_12" | sample == "w13_FL_P12_19") + theme_minimal()

2.4.3 Taking out the outliers

my_samples<-data[data$PC1 < 0,]$sample
normalized.data<-normalized.data[rownames(normalized.data) %in% my_samples,]

pca_plot(normalized.data)

2.4.4 Batch effect removal

my_eset <- t(normalized.data)
my_eset <- my_eset[!duplicated(rownames(my_eset)),]
my_peset <-sample_table[rownames(sample_table) %in% colnames(my_eset),]
my_eset  <- my_eset[,order(match(colnames(my_eset),rownames(my_peset)))]


pd <- new("AnnotatedDataFrame", data=my_peset)
my_eset <- ExpressionSet(assayData = my_eset, pd)

pheno <- pData(my_eset)
edata <- exprs(my_eset)

batch=pheno$batch

combat_edata1 = ComBat(dat=edata, batch=batch, mod=NULL, par.prior=TRUE, prior.plots=FALSE)
## Standardizing Data across genes
combat_edata1 <- t(combat_edata1)
pca_plot(combat_edata1)

2.4.4.1 Repeat with IL7R

il7_peset <- rownames_to_column(my_peset, var = "sample") %>% dplyr::filter( grepl("IL7R", Phenotype ))
il7_eset <- my_eset[,which(colnames(my_eset) %in% il7_peset$sample)]

pheno <- pData(il7_eset)
edata <- exprs(il7_eset)

batch=pheno$batch

combat_edata1 = ComBat(dat=edata, batch=batch, mod=NULL, par.prior=TRUE, prior.plots=FALSE)
## Standardizing Data across genes
combat_edata1 <- t(combat_edata1)

pca_plot(combat_edata1)

2.4.5 PCA without normalizing the FPKMs

my_fpkms <- t(fpkms[,3:61])

pca_plot(my_fpkms)

2.5 PCA with counts

2.5.1 Using scater normalization

# mar_22_counts <- read.delim('myriad/big_counts')
# nov_20_counts <- read.delim('20_nov_2018/myriad/big_counts')
# 
# big_counts <- left_join(rownames_to_column(nov_20_counts, "ensgene"),rownames_to_column(mar_22_counts,"ensgene"))
# #matching names and orders
# 
# big_counts <- dplyr::rename(big_counts,
#                                BM_P5_11       = C23_N728_S505,
#                                BM_P10_11      = B04_N704_S503,
#                                BM_P12_11      = B06_N706_S503,
#                                CS19_P5_11     = B08_N710_S503,
#                                CS19_P12_11    = B12_N715_S503,
#                                BM1_P5_12      = B14_N718_S503,
#                                BM1_P10_12     = B16_N720_S503,
#                                BM1_P12_12     = B18_N722_S503,
#                                BM2_P5_12      = B20_N724_S503,
#                                BM2_P10_12     = B22_N727_S503,
#                                BM2_P12_12     = F20_N724_S508,
#                                CB_P5_12       = E23_N728_S507,
#                                CB_P10_12      = D04_N704_S506,
#                                CB_P12_12      = D06_N706_S506,
#                                CS22_P5_12     = D08_N710_S506,
#                                CS22_P10_12    = D10_N712_S506,
#                                CS22_P12_12    = D12_N715_S506,
#                                CS20_P5_12     = D14_N718_S506,
#                                CS20_P10_12    = D16_N720_S506,
#                                CS20_P12_12    = D18_N722_S506,
#                                FL13w_P5_13    = D20_N724_S506,
#                                FL13w_P10_13   = D22_N727_S506,
#                                FL13w_P12_13   = F22_N727_S508,
#                                CS23_P5_13     = G23_N728_S510,
#                                CS23_P10_13    = F04_N704_S508,
#                                CS23_P12_13    = F06_N706_S508,
#                                CS22_P5_19     = F08_N710_S508,
#                                CS22_P10_19    = F10_N712_S508,
#                                CS22_P12_19    = F12_N715_S508,
#                                w13_FL_P5_19   = F14_N718_S508,
#                                w13_FL_P10_19  = F16_N720_S508,
#                                w13_FL_P12_19  = F18_N722_S508)
# 
# 
# temp_counts <- big_counts[,2:60][,order(match(colnames(big_counts[,2:60]),rownames(sample_table)))]
# big_counts[2:60] <- NULL
# big_counts <- cbind(big_counts,temp_counts)
# 
# saveRDS(big_counts,"big_counts.rds")

big_counts <- readRDS('big_counts.rds')

count_matrix <- as.matrix(big_counts[,2:length(colnames(big_counts))])
colnames(count_matrix) <- rownames(sample_table)
rownames(count_matrix) <- big_counts$ensgene

sce <- SingleCellExperiment(list(counts = count_matrix),
                            colData = sample_table)
sce <- sce[rowSums(counts(sce)) >  0,]
sce <- calculateQCMetrics(sce)
## prepare total count and total features data

my_df <- data.frame("sample_id" <- colnames(sce), "total_counts" = sce$total_counts,
                    "total_features" = sce$total_features_by_counts, "batch" = sce$batch )
ggplot(my_df,aes(total_counts, fill = batch)) + geom_histogram(bins = 50) + 
  theme_minimal() + ggtitle("Histogram of total counts") + ylab("number of samples") + xlab("total counts")

ggplot(my_df,aes(total_features, fill = batch)) + geom_histogram(bins = 50) + 
  theme_minimal() + ggtitle("Histogram of total features") + ylab("number of samples") + xlab("total features")

2.5.2 PCA without batch effect removal

sizeFactors(sce) <- librarySizeFactors(sce)
sce <- normalize(sce)

sce <- runPCA(sce)

data <- reducedDim(sce)
percent_var_PC1<- paste("PC1", sprintf('(%0.1f%% explained var.)', attr(data, 'percentVar')[1] * 100 ))
percent_var_PC2<- paste("PC2", sprintf('(%0.1f%% explained var.)', attr(data, 'percentVar')[2] * 100 ))

data <- data.frame(data)
data<-left_join(rownames_to_column(data), rownames_to_column(sample_table))

ggplot(data,aes(PC1,PC2, colour = Phenotype, shape = batch )) + geom_point(size = 3 ) + 
  geom_label_repel(aes(label = rowname), size = 2,box.padding   = 0.1,point.padding = 0.1,
                   segment.color = 'grey50') + theme_minimal() + xlab(percent_var_PC1) + ylab(percent_var_PC2)

2.5.3 PCA with IL7R only

sce <- sce[,grep("IL7R", sce$Phenotype)]

sce <- runPCA(sce)

data <- reducedDim(sce)
percent_var_PC1<- paste("PC1", sprintf('(%0.1f%% explained var.)', attr(data, 'percentVar')[1] * 100 ))
percent_var_PC2<- paste("PC2", sprintf('(%0.1f%% explained var.)', attr(data, 'percentVar')[2] * 100 ))

data <- data.frame(data)
data<-left_join(rownames_to_column(data), rownames_to_column(sample_table))

ggplot(data,aes(PC1,PC2, colour = pools, shape = batch )) + geom_point(size = 3 ) + 
  geom_label_repel(aes(label = rowname), size = 2,box.padding   = 0.1,point.padding = 0.1,
                   segment.color = 'grey50') + theme_minimal() + xlab(percent_var_PC1) + ylab(percent_var_PC2)

2.6 DEseq2

library(DESeq2)
rownames(big_counts) <- big_counts$ensgene
big_counts$ensgene <- NULL
dds <- DESeqDataSetFromMatrix(big_counts, colData = sample_table, design = ~Phenotype)
my_vst <- vst(dds)

pcaData <- DESeq2::plotPCA(my_vst, intgroup =c("Phenotype","batch","stage","pools"),returnData = TRUE)
percentVar <- round(100 * attr(pcaData, "percentVar"))


ggplot(pcaData,aes(PC1,PC2,colour = Phenotype, shape = batch)) + geom_point(size = 3 ) +
        xlab(paste0("PC1: ",percentVar[1],"% variance")) +
        ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
          geom_label_repel(aes(label = name), size = 2,box.padding   = 0.1,point.padding = 0.1,
                   segment.color = 'grey50') +
        theme_minimal()

2.6.1 Genes driving PC1 and PC2

top_contribs = function(object) {
  # calculate the variance for each gene
  rv <- rowVars(assay(object))

  # select the 1000 top genes by variance
  select <- order(rv, decreasing=TRUE)[seq_len(min(1000, length(rv)))]

  # perform a PCA on the data in assay(x) for the selected genes
  pca <- prcomp(t(assay(object)[select,]))

  # the contribution to the total variance for each component
  percentVar <- pca$sdev^2 / sum( pca$sdev^2 )

  # Top 20 contributers to PC1 PC2
  PCA1_contrib <- sort(abs(pca$rotation[,1]), decreasing = TRUE )[1:20]
  PCA2_contrib <- sort(abs(pca$rotation[,2]), decreasing = TRUE )[1:20]
  PCA_contrib <- c(PCA1_contrib, PCA2_contrib)
  PCA_contrib <- data.frame("ensgene" = names(PCA_contrib), PCA_contrib)



  PCA_contrib <- cbind(PCA_contrib, data.frame("PC" = c(rep("PC1",20),rep("PC2","20"))))
  PCA_contrib <- left_join(PCA_contrib, grch38, by = "ensgene") %>% dplyr::select("PC","symbol", "biotype")
  return(PCA_contrib)
}

datatable(top_contribs(my_vst))

2.6.2 DESeq with IL7R only

dds <- dds[,colData(dds)$PCA_only_IL7R == "yes"]


my_vst <- vst(dds)

pcaData <- DESeq2::plotPCA(my_vst, intgroup =c("Phenotype","batch","stage", "pools"),returnData = TRUE)
percentVar <- round(100 * attr(pcaData, "percentVar"))


ggplot(pcaData,aes(PC1,PC2,colour = pools, shape = Phenotype )) + geom_point(size = 3 ) +
        xlab(paste0("PC1: ",percentVar[1],"% variance")) +
        ylab(paste0("PC2: ",percentVar[2],"% variance")) + 
                  geom_label_repel(aes(label = name), size = 2,box.padding   = 0.1,point.padding = 0.1,
                   segment.color = 'grey50') +
       theme_minimal() 

2.6.3 Genes driving PC1 and PC2 (IL7 only)

datatable(top_contribs(my_vst))

3 Differential Gene Expression

3.1 IL7R+KIT w12_13 v BM

coldata <- sample_table[sample_table$diff_groups == 1 & ( sample_table$pools == "W12_13" | sample_table$pools == "BM"), ]

run_deseq <- function(coldata,contrast1){
counts <- big_counts[,colnames(big_counts) %in% rownames(coldata)]
dds <- DESeqDataSetFromMatrix(counts, colData = coldata, design = ~batch + pools)

deseq <- DESeq(dds)

res <- results(deseq, contrast = c("pools", contrast1, "BM"))
resOrdered <- res[order(res$padj),]
resOrdered <- data.frame(resOrdered)
resOrdered <- left_join(rownames_to_column(resOrdered, var = "ensgene"), grch38, by = "ensgene") %>% 
  dplyr::select(symbol,log2FoldChange,padj,biotype)
for_DT <- resOrdered[1:500,]
return(list(res = resOrdered, for_Datatable = for_DT))
}
my_res <- run_deseq(coldata, "W12_13")
datatable(my_res$for_Datatable)
hallmark <- gmtPathways("~/genome_apps/GSEA/h.all.v6.2.symbols.gmt")

plot_gsea <- function(res){
res <- res[complete.cases(res),]
res$fcSign <- sign(res$log2FoldChange)
res$logP <- -log10(res$padj)
res$metric <- res$logP/res$fcSign
y<-res[,c("symbol", "metric")]
geneList <- y$metric
names(geneList) <- y$symbol
geneList <- geneList[order(geneList, decreasing = T)]
fgseaRes <- fgsea(hallmark, geneList, nperm=10000, maxSize = 500)
fgseaRes <- fgseaRes[fgseaRes$padj < 0.05,]
plotGseaTable(hallmark[fgseaRes$pathway], geneList, fgseaRes, gseaParam = 0.4)
}

plot_gsea(my_res$res)

3.2 IL7R+KIT w8_10 v BM

coldata <- sample_table[sample_table$diff_groups == 1 & ( sample_table$pools == "W8_10" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata, "W8_10")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.3 IL7R+KIT CS19_23 v BM

coldata <- sample_table[sample_table$diff_groups == 1 & ( sample_table$pools == "CS19_23" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"CS19_23")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.4 IL7R+KIT CB v BM

coldata <- sample_table[sample_table$diff_groups == 1 & ( sample_table$pools == "CB" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata, "CB")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.5 CD34+CD38-CD45RA- w12_13 v BM

coldata <- sample_table[sample_table$diff_groups == 2 & ( sample_table$pools == "W12_13" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata, "W12_13")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.6 CD34+CD38-CD45RA- w8_10 v BM

coldata <- sample_table[sample_table$diff_groups == 2 & ( sample_table$pools == "W8_10" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"W8_10")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.7 CD34+CD38-CD45RA- CS19_23 v BM

coldata <- sample_table[sample_table$diff_groups == 2 & ( sample_table$pools == "CS19_23" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata, "CS19_23")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.8 CD34+CD38-CD45RA- CB v BM

coldata <- sample_table[sample_table$diff_groups == 2 & ( sample_table$pools == "CB" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"CB")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.9 CD34+CD19+ w12_13 v BM

coldata <- sample_table[sample_table$diff_groups == 3 & ( sample_table$pools == "W12_13" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata, "W12_13")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.10 CD34+CD19+ w8_10 v BM

coldata <- sample_table[sample_table$diff_groups == 3 & ( sample_table$pools == "W8_10" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"W8_10")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.11 CD34+CD19+ CS19_23 v BM

coldata <- sample_table[sample_table$diff_groups == 3 & ( sample_table$pools == "CS19_23" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"CS19_23")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

3.12 CD34+CD19+ CB v BM

coldata <- sample_table[sample_table$diff_groups == 3 & ( sample_table$pools == "CB" | sample_table$pools == "BM"), ]

my_res <- run_deseq(coldata,"CB")
datatable(my_res$for_Datatable)
plot_gsea(my_res$res)

LS0tCnRpdGxlOiAiRXhwbG9yaW5nIEh1bWFuIFByaW1hcnkgU2FtcGxlcyIKYXV0aG9yOiA8YSBocmVmPSJodHRwczovL2NoZWxhLWphbWVzLmdpdGh1Yi5pby8iPiA8aDM+IENoZWxhIEphbWVzIDwvaDM+IDwvYT4gXG5ld2xpbmUgQ2FuY2VyIEluc3RpdHV0ZSwgVUNMLCBVSwpkYXRlOiAyMiBNYXJjaCAyMDE5Cm91dHB1dDoKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRoZW1lOiB1bml0ZWQKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAga2VlcF9tZDogZmFsc2UKICAgIGVuY29kaW5nOiAiVVRGLTgiCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpodG1sdG9vbHM6OnRhZ0xpc3Qocm1hcmtkb3duOjpodG1sX2RlcGVuZGVuY3lfZm9udF9hd2Vzb21lKCkpCmtuaXRyOjpvcHRzX2NodW5rJHNldChldmFsID0gVFJVRSwgY2FjaGUgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpCmBgYAoKCmBgYHtyLCAgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHN2YSkKbGlicmFyeShkcGx5cikKbGlicmFyeShwcmVwcm9jZXNzQ29yZSkKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KEJpb2Jhc2UpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KHNjYXRlcikKbGlicmFyeShnZ2hpZ2hsaWdodCkKbGlicmFyeShhbm5vdGFibGVzKQpsaWJyYXJ5KERFU2VxMikKbGlicmFyeShmZ3NlYSkKbGlicmFyeShEVCkKYGBgCgojIEludmVzdGlnYXRpbmcgaGFlbWF0b3BvaWV0aWMgcHJvZ2VuaXRvcnMgZnJvbSBlYXJseSBmb2V0YWwgbGl2ZXIgCgpJbiBvcmRlciB0byBpbnZlc3RpZ2F0ZSB0aGUgcHJvcGVydGllcyBvZiBhIG5vdmVsIGx5bXBoby1teWVsb2lkIHByb2dlbml0b3IgY2VsbCB3ZSBpc29sYXRlZCBjZWxscyBmcm9tIGVhcmx5IGZvZXRhbCBsaXZlcgoKIyBUcmFuc2NyaXB0aW9uYWwgcHJvZmlsZSBQQ0EgYW5kIGRpZmZlcmVudGlhbCBnZW5lIGV4cHJlc3Npb24gKERHQSkKCiMjIFNvcnRpbmcKCklzb2xhdGVkIGNlbGxzIHdlcmUgc29ydGVkIHVzaW5nIGEgdmFyaWV0eSBvZiBjZWxsIG1hcmtlcnMKCiMjIFJOQS1zZXEKClJOQSB3YXMgaXNvbGF0ZWQgYW5kIHNlcXVlbmNlZCBmcm9tIHRoZSB2YXJpb3VzIGNlbGwgdHlwZXMuCgojIyBTYW1wbGUgc3VtbWFyeQoKYGBge3J9CnNhbXBsZV90YWJsZSA8LSByZWFkLmRlbGltKCdjaGFybG90dGFfc2ltcGxpZmllZF90YWJsZS50c3YnLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgpyb3duYW1lcyhzYW1wbGVfdGFibGUpIDwtIHNhbXBsZV90YWJsZSROYW1lCnNhbXBsZV90YWJsZSROYW1lIDwtIE5VTEwKc2FtcGxlX3RhYmxlJFNhbXBsZUlEIDwtIE5VTEwKc2FtcGxlX3RhYmxlJGJhdGNoIDwtIGMocmVwKCJub3ZfMTgiLCAyNyksIHJlcCgibWFyXzE5IiwzMikpCnNhbXBsZV90YWJsZSRzdGFnZSA8LSBjKCJ3MTIiLCJ3MTIiLCJ3MTAiLCJ3MTAiLCJ3MTAiLCJDUzE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNTMTkiLCJDUzE5IiwiQ0IiLCJDQiIsIkNCIiwiQ1MxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICJDUzE2IiwiQ0IiLCJDQiIsIkNCIiwidzEzIiwidzEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgIkNTMjAiLCJDUzIwIiwiQ1MyMCIsInc4IiwidzgiLCJ3OCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJCTSIsIkJNIiwiQk0iLCJCTSIsIkJNIiwiQk0iLCJDUzE5IgogICAgICAgICAgICAgICAgICAgICAgICAsIkNTMTkiLCJCTSIsIkJNIiwiQk0iLCJCTSIsIkJNIiwiQk0iLAogICAgICAgICAgICAgICAgICAgICAgICAiQ0IiLCJDQiIsIkNCIiwiQ1MyIiwiQ1MyIiwiQ1MyIiwiQ1MyIgogICAgICAgICAgICAgICAgICAgICAgICAsIkNTMiIsIkNTMiIsIncxMyIsIncxMyIsIncxMyIsIkNTMjMiLAogICAgICAgICAgICAgICAgICAgICAgICAiQ1MyMyIsIkNTMjMiLCJDUzIyIiwiQ1MyMiIsIkNTMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAidzEzIiwidzEzIiwidzEzIikKCnNhbXBsZV90YWJsZSRkaWZmX2dyb3VwcyA8LSBjKDEsMiwzLDEsMiwzLDEsMiwzLDEsMiwyLDEsMywxLDIsMywyLDMsMSwyLDMsMiwxLDEsMiwzLDMsMiwxLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSwzLDIsMSkKCnNhbXBsZV90YWJsZSRwb29scyA8LSBjKCJXMTJfMTMiLCJXMTJfMTMiLCJXOF8xMCIsIlc4XzEwIiwiVzhfMTAiLCJDUzE5XzIzIiwiQ1MxOV8yMyIsIkNTMTlfMjMiLCJDQiIsIkNCIiwiQ0IiLCJDUzE2IiwiQ1MxNiIsIkNCIiwiQ0IiLCJDQiIsIlcxMl8xMyIsIlcxMl8xMyIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiQ1MxOV8yMyIsIlc4XzEwIiwiVzhfMTAiLCJXOF8xMCIsIkJNIiwiQk0iLCJCTSIsIkJNIiwiQk0iLCJCTSIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiQk0iLCJCTSIsIkJNIiwiQk0iLCJCTSIsIkJNIiwiQ0IiLCJDQiIsIkNCIiwiQ1MxOV8yMyIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiQ1MxOV8yMyIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiVzEyXzEzIiwiVzEyXzEzIiwiVzEyXzEzIiwiQ1MxOV8yMyIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiQ1MxOV8yMyIsIkNTMTlfMjMiLCJDUzE5XzIzIiwiVzEyXzEzIiwiVzEyXzEzIiwiVzEyXzEzIikKCmRhdGF0YWJsZShzYW1wbGVfdGFibGUpICU+JSAKICBmb3JtYXRTdHlsZSgiZGlmZl9ncm91cHMiLCBiYWNrZ3JvdW5kQ29sb3IgPSBzdHlsZUVxdWFsKGMoMSwyLDMpLCBjKCIjRUFEM0JGIiwiI0FBOTQ4NiIsICIjQjY4NTREIikpKSAlPiUKICBmb3JtYXRTdHlsZSgicG9vbHMiLCBiYWNrZ3JvdW5kQ29sb3IgPSBzdHlsZUVxdWFsKGMoIlcxMl8xMyIsIkNTMTlfMjMiLCJDQiIsIlc4XzEwIiwiQk0iLCJDUzE2IiksIGMoIiM5OTg2QTUiLCIjNzk0MDJFIiwgIiNDQ0JBNzIiLCIjRjNERjZDIiwiI0Q5RDBEMyIsIiM4RDg2ODAiKSkpCgpgYGAKCiMjIFBDQSAKCiMjIyBQQ0EgJ0FsbCcgd29ya2luZyB3aXRoIEZQS01TIGFuZCBbcXVhbnRpbGUgbm9ybWFsaXphdGlvbl0oaHR0cDovL2dlbm9taWNzY2xhc3MuZ2l0aHViLmlvL2Jvb2svcGFnZXMvbm9ybWFsaXphdGlvbi5odG1sKQoKYGBge3J9CgojbWFyXzIyXzE5X2Zwa21zIDwtIHJlYWQuZGVsaW0oJ215cmlhZC8yMl8wM18xOV9mcGttcycsIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSApIAojbm92XzIwXzE4X2Zwa21zIDwtIHJlYWQuZGVsaW0oJzIwX25vdl8yMDE4L215cmlhZC8yMF9ub3ZfMThfZnBrbXMnLCBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UgKQoKbWFyXzIyXzE5X2Zwa21zIDwtIHJlYWRSRFMoIm1hcl8yMl8xOV9mcGttcy5SRFMiKQpub3ZfMjBfMThfZnBrbXMgPC0gcmVhZFJEUygibm92XzIwXzE4X2Zwa21zLlJEUyIpCgptYXJfMjJfMTlfZnBrbXM8LWRwbHlyOjpyZW5hbWUobWFyXzIyXzE5X2Zwa21zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk1fUDVfMTEgICAgICAgPSBDMjNfTjcyOF9TNTA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk1fUDEwXzExICAgICAgPSBCMDRfTjcwNF9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk1fUDEyXzExICAgICAgPSBCMDZfTjcwNl9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MxOV9QNV8xMSAgICAgPSBCMDhfTjcxMF9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MxOV9QMTJfMTEgICAgPSBCMTJfTjcxNV9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0xX1A1XzEyICAgICAgPSBCMTRfTjcxOF9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0xX1AxMF8xMiAgICAgPSBCMTZfTjcyMF9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0xX1AxMl8xMiAgICAgPSBCMThfTjcyMl9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0yX1A1XzEyICAgICAgPSBCMjBfTjcyNF9TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0yX1AxMF8xMiAgICAgPSBCMjJfTjcyN19TNTAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0yX1AxMl8xMiAgICAgPSBGMjBfTjcyNF9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0JfUDVfMTIgICAgICAgPSBFMjNfTjcyOF9TNTA3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0JfUDEwXzEyICAgICAgPSBEMDRfTjcwNF9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0JfUDEyXzEyICAgICAgPSBEMDZfTjcwNl9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QNV8xMiAgICAgPSBEMDhfTjcxMF9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTBfMTIgICAgPSBEMTBfTjcxMl9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTJfMTIgICAgPSBEMTJfTjcxNV9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMF9QNV8xMiAgICAgPSBEMTRfTjcxOF9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMF9QMTBfMTIgICAgPSBEMTZfTjcyMF9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMF9QMTJfMTIgICAgPSBEMThfTjcyMl9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkwxM3dfUDVfMTMgICAgPSBEMjBfTjcyNF9TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkwxM3dfUDEwXzEzICAgPSBEMjJfTjcyN19TNTA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkwxM3dfUDEyXzEzICAgPSBGMjJfTjcyN19TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyM19QNV8xMyAgICAgPSBHMjNfTjcyOF9TNTEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyM19QMTBfMTMgICAgPSBGMDRfTjcwNF9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyM19QMTJfMTMgICAgPSBGMDZfTjcwNl9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QNV8xOSAgICAgPSBGMDhfTjcxMF9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTBfMTkgICAgPSBGMTBfTjcxMl9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTJfMTkgICAgPSBGMTJfTjcxNV9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzEzX0ZMX1A1XzE5ICAgPSBGMTRfTjcxOF9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzEzX0ZMX1AxMF8xOSAgPSBGMTZfTjcyMF9TNTA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzEzX0ZMX1AxMl8xOSAgPSBGMThfTjcyMl9TNTA4KQoKZnBrbXMgPC0gbGVmdF9qb2luKG5vdl8yMF8xOF9mcGttcyxtYXJfMjJfMTlfZnBrbXMsIGJ5ID0gYygiZW5zZ2VuZSIgPSAiZW5zZ2VuZSIgKSkKZnBrbXMgPC0gZHBseXI6OnJlbmFtZShmcGttcyxzeW1ib2wgPSBzeW1ib2wueCkKZnBrbXMkc3ltYm9sLnkgPC0gTlVMTApteV9yb3dzIDwtIGFwcGx5KGZwa21zWywzOmxlbmd0aChjb2xuYW1lcyhmcGttcykpXSwgMSwgbWF4KSA+PTU7CmZwa21zIDwtIGZwa21zW215X3Jvd3MsXQpmcGttcyA8LSBmcGttc1tjb21wbGV0ZS5jYXNlcyhmcGttcyksXQp0ZW1wX2Zwa21zIDwtIGZwa21zWywzOjYxXVssb3JkZXIobWF0Y2goY29sbmFtZXMoZnBrbXNbLDM6NjFdKSxyb3duYW1lcyhzYW1wbGVfdGFibGUpKSldCmZwa21zWywzOjYxXTwtTlVMTApmcGttcyA8LSBjYmluZChmcGttcyx0ZW1wX2Zwa21zKQpybSh0ZW1wX2Zwa21zKQpmcGttc19jb3VudHNfb25seSA8LSBmcGttc1ssMzpsZW5ndGgoY29sbmFtZXMoZnBrbXMpKV0KIyMgTG9nIHRyYW5zZm9ybSB0aGUgZGF0YQpsb2cuZGF0YSA9IGxvZzIoZnBrbXNfY291bnRzX29ubHkrMSkKCiMjIFF1YW50aWxlIG5vcm1hbGl6YXRpb24Kbm9ybWFsaXplZC5kYXRhID0gbm9ybWFsaXplLnF1YW50aWxlcyhhcy5tYXRyaXgobG9nLmRhdGEpKSAjIEEgcXVhbnRpbGUgbm9ybWFsaXphdGlvbi4KCiMjIENvcHkgdGhlIHJvdyBhbmQgY29sdW1uIG5hbWVzIGZyb20gZGF0YSB0byBkYXRhMjoKcm93bmFtZXMobm9ybWFsaXplZC5kYXRhKSA9IGZwa21zJGVuc2dlbmUKY29sbmFtZXMobm9ybWFsaXplZC5kYXRhKSA9IGNvbG5hbWVzKGZwa21zWywzOmxlbmd0aChjb2xuYW1lcyhmcGttcykpXSkKCiMjIFRyYW5zcG9zZSB0aGUgbWF0cml4IGJhY2sgZm9yIFBDQQpub3JtYWxpemVkLmRhdGEgPSB0KG5vcm1hbGl6ZWQuZGF0YSkKCmZpdCA8LSBwcmNvbXAobm9ybWFsaXplZC5kYXRhKQoKeD0iUEMxIgp5PSJQQzIiCngubGFiID0gcGFzdGUoeCwgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgMTAwICogZml0JHNkZXZbd2hpY2goY29sbmFtZXMoZml0JHgpID09IHgpXV4yL3N1bShmaXQkc2Rldl4yKSkpCnkubGFiID0gcGFzdGUoeSwgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgMTAwICogZml0JHNkZXZbd2hpY2goY29sbmFtZXMoZml0JHgpID09IHkpXV4yL3N1bShmaXQkc2Rldl4yKSkpCmRhdGEgPC0gZGF0YS5mcmFtZShmaXQkeCkKZGF0YTwtcm93bmFtZXNfdG9fY29sdW1uKGRhdGEsIHZhciA9ICJzYW1wbGUiKQpkYXRhPC1sZWZ0X2pvaW4oZGF0YSxyb3duYW1lc190b19jb2x1bW4oc2FtcGxlX3RhYmxlLCB2YXIgPSAic2FtcGxlX2lkIiksIGJ5ID0gYygic2FtcGxlIiA9ICJzYW1wbGVfaWQiKSkKCiMjID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMjIFByZWxpbWluYXJ5IFBDQSBwcmUtYmF0Y2ggbm9ybWFsaXp0aW9uCiMjID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CnBjYV9wbG90IDwtIGZ1bmN0aW9uKGRhdGEpIHsKZml0IDwtIHByY29tcChkYXRhKQoKeD0iUEMxIgp5PSJQQzIiCngubGFiID0gcGFzdGUoeCwgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgMTAwICogZml0JHNkZXZbd2hpY2goY29sbmFtZXMoZml0JHgpID09IHgpXV4yL3N1bShmaXQkc2Rldl4yKSkpCnkubGFiID0gcGFzdGUoeSwgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgMTAwICogZml0JHNkZXZbd2hpY2goY29sbmFtZXMoZml0JHgpID09IHkpXV4yL3N1bShmaXQkc2Rldl4yKSkpCmRhdGEgPC0gZGF0YS5mcmFtZShmaXQkeCkKZGF0YTwtcm93bmFtZXNfdG9fY29sdW1uKGRhdGEsIHZhciA9ICJzYW1wbGUiKQpkYXRhPC1sZWZ0X2pvaW4oZGF0YSxyb3duYW1lc190b19jb2x1bW4oc2FtcGxlX3RhYmxlLCB2YXIgPSAic2FtcGxlX2lkIiksIGJ5ID0gYygic2FtcGxlIiA9ICJzYW1wbGVfaWQiKSkKCgpnZ3Bsb3QoZGF0YSxhZXMoUEMxLFBDMixjb2xvdXIgPSBiYXRjaCxzaGFwZSA9IFBoZW5vdHlwZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICBnZW9tX2xhYmVsX3JlcGVsKGFlcyhsYWJlbCA9IHNhbXBsZSksCiAgc2l6ZSA9IDIsCiAgYm94LnBhZGRpbmcgICA9IDAuMSwgCiAgcG9pbnQucGFkZGluZyA9IDAuMSwKICBzZWdtZW50LmNvbG9yID0gJ2dyZXk1MCcpICsKICB4bGFiKGxhYmVsID0geC5sYWIpICsKICB5bGFiKGxhYmVsID0geS5sYWIpICsKICB0aGVtZV9taW5pbWFsKCkKfQoKcGNhX3Bsb3Qobm9ybWFsaXplZC5kYXRhKQpgYGAKCgojIyMgV2h5IGFyZSB0aGV5IG91dGxpZXJzPwoKU29tZSBvZiB0aGVtIGhhdmUgb3ZlcnJlcHJlc2VudGVkIHNlcXVlbmNlcz8KCiFbb3ZlcnJlcHJlc2VudGVkXShvdmVycmVwcmVzZW50ZWQucG5nKQoKYGBge3J9CmdncGxvdChkYXRhLGFlcyhQQzEsUEMyLGNvbG91ciA9IGJhdGNoLHNoYXBlID0gUGhlbm90eXBlKSkgKyBnZW9tX3BvaW50KHNpemUgPSAyKSAgKyBnZ2hpZ2hsaWdodChzYW1wbGUgPT0gIkNTMjJfUDEwXzEyIiB8IHNhbXBsZSA9PSAiQ1MyMl9QMTJfMTIiIHwgc2FtcGxlID09ICJ3MTNfRkxfUDEyXzE5IikgKyB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyNUYWtpbmcgb3V0IHRoZSBvdXRsaWVycwoKYGBge3J9Cm15X3NhbXBsZXM8LWRhdGFbZGF0YSRQQzEgPCAwLF0kc2FtcGxlCm5vcm1hbGl6ZWQuZGF0YTwtbm9ybWFsaXplZC5kYXRhW3Jvd25hbWVzKG5vcm1hbGl6ZWQuZGF0YSkgJWluJSBteV9zYW1wbGVzLF0KCnBjYV9wbG90KG5vcm1hbGl6ZWQuZGF0YSkKCmBgYAoKIyMjQmF0Y2ggZWZmZWN0IHJlbW92YWwKCmBgYHtyfQpteV9lc2V0IDwtIHQobm9ybWFsaXplZC5kYXRhKQpteV9lc2V0IDwtIG15X2VzZXRbIWR1cGxpY2F0ZWQocm93bmFtZXMobXlfZXNldCkpLF0KbXlfcGVzZXQgPC1zYW1wbGVfdGFibGVbcm93bmFtZXMoc2FtcGxlX3RhYmxlKSAlaW4lIGNvbG5hbWVzKG15X2VzZXQpLF0KbXlfZXNldCAgPC0gbXlfZXNldFssb3JkZXIobWF0Y2goY29sbmFtZXMobXlfZXNldCkscm93bmFtZXMobXlfcGVzZXQpKSldCgoKcGQgPC0gbmV3KCJBbm5vdGF0ZWREYXRhRnJhbWUiLCBkYXRhPW15X3Blc2V0KQpteV9lc2V0IDwtIEV4cHJlc3Npb25TZXQoYXNzYXlEYXRhID0gbXlfZXNldCwgcGQpCgpwaGVubyA8LSBwRGF0YShteV9lc2V0KQplZGF0YSA8LSBleHBycyhteV9lc2V0KQoKYmF0Y2g9cGhlbm8kYmF0Y2gKCmNvbWJhdF9lZGF0YTEgPSBDb21CYXQoZGF0PWVkYXRhLCBiYXRjaD1iYXRjaCwgbW9kPU5VTEwsIHBhci5wcmlvcj1UUlVFLCBwcmlvci5wbG90cz1GQUxTRSkKY29tYmF0X2VkYXRhMSA8LSB0KGNvbWJhdF9lZGF0YTEpCnBjYV9wbG90KGNvbWJhdF9lZGF0YTEpCgpgYGAKCiMjIyNSZXBlYXQgd2l0aCBJTDdSCgpgYGB7cn0KaWw3X3Blc2V0IDwtIHJvd25hbWVzX3RvX2NvbHVtbihteV9wZXNldCwgdmFyID0gInNhbXBsZSIpICU+JSBkcGx5cjo6ZmlsdGVyKCBncmVwbCgiSUw3UiIsIFBoZW5vdHlwZSApKQppbDdfZXNldCA8LSBteV9lc2V0Wyx3aGljaChjb2xuYW1lcyhteV9lc2V0KSAlaW4lIGlsN19wZXNldCRzYW1wbGUpXQoKcGhlbm8gPC0gcERhdGEoaWw3X2VzZXQpCmVkYXRhIDwtIGV4cHJzKGlsN19lc2V0KQoKYmF0Y2g9cGhlbm8kYmF0Y2gKCmNvbWJhdF9lZGF0YTEgPSBDb21CYXQoZGF0PWVkYXRhLCBiYXRjaD1iYXRjaCwgbW9kPU5VTEwsIHBhci5wcmlvcj1UUlVFLCBwcmlvci5wbG90cz1GQUxTRSkKY29tYmF0X2VkYXRhMSA8LSB0KGNvbWJhdF9lZGF0YTEpCgpwY2FfcGxvdChjb21iYXRfZWRhdGExKQoKYGBgCgoKIyMjIFBDQSB3aXRob3V0IG5vcm1hbGl6aW5nIHRoZSBGUEtNcwoKYGBge3J9Cm15X2Zwa21zIDwtIHQoZnBrbXNbLDM6NjFdKQoKcGNhX3Bsb3QobXlfZnBrbXMpCgpgYGAKCiMjUENBIHdpdGggY291bnRzCiMjI1VzaW5nIFtzY2F0ZXJdKGh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9zY2F0ZXIuaHRtbCkgbm9ybWFsaXphdGlvbiAKCmBgYHtyfQojIG1hcl8yMl9jb3VudHMgPC0gcmVhZC5kZWxpbSgnbXlyaWFkL2JpZ19jb3VudHMnKQojIG5vdl8yMF9jb3VudHMgPC0gcmVhZC5kZWxpbSgnMjBfbm92XzIwMTgvbXlyaWFkL2JpZ19jb3VudHMnKQojIAojIGJpZ19jb3VudHMgPC0gbGVmdF9qb2luKHJvd25hbWVzX3RvX2NvbHVtbihub3ZfMjBfY291bnRzLCAiZW5zZ2VuZSIpLHJvd25hbWVzX3RvX2NvbHVtbihtYXJfMjJfY291bnRzLCJlbnNnZW5lIikpCiMgI21hdGNoaW5nIG5hbWVzIGFuZCBvcmRlcnMKIyAKIyBiaWdfY291bnRzIDwtIGRwbHlyOjpyZW5hbWUoYmlnX2NvdW50cywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk1fUDVfMTEgICAgICAgPSBDMjNfTjcyOF9TNTA1LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCTV9QMTBfMTEgICAgICA9IEIwNF9ONzA0X1M1MDMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJNX1AxMl8xMSAgICAgID0gQjA2X043MDZfUzUwMywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MxOV9QNV8xMSAgICAgPSBCMDhfTjcxMF9TNTAzLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUzE5X1AxMl8xMSAgICA9IEIxMl9ONzE1X1M1MDMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJNMV9QNV8xMiAgICAgID0gQjE0X043MThfUzUwMywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0xX1AxMF8xMiAgICAgPSBCMTZfTjcyMF9TNTAzLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCTTFfUDEyXzEyICAgICA9IEIxOF9ONzIyX1M1MDMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJNMl9QNV8xMiAgICAgID0gQjIwX043MjRfUzUwMywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk0yX1AxMF8xMiAgICAgPSBCMjJfTjcyN19TNTAzLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCTTJfUDEyXzEyICAgICA9IEYyMF9ONzI0X1M1MDgsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENCX1A1XzEyICAgICAgID0gRTIzX043MjhfUzUwNywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0JfUDEwXzEyICAgICAgPSBEMDRfTjcwNF9TNTA2LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDQl9QMTJfMTIgICAgICA9IEQwNl9ONzA2X1M1MDYsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENTMjJfUDVfMTIgICAgID0gRDA4X043MTBfUzUwNiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTBfMTIgICAgPSBEMTBfTjcxMl9TNTA2LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUzIyX1AxMl8xMiAgICA9IEQxMl9ONzE1X1M1MDYsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENTMjBfUDVfMTIgICAgID0gRDE0X043MThfUzUwNiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMF9QMTBfMTIgICAgPSBEMTZfTjcyMF9TNTA2LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUzIwX1AxMl8xMiAgICA9IEQxOF9ONzIyX1M1MDYsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZMMTN3X1A1XzEzICAgID0gRDIwX043MjRfUzUwNiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkwxM3dfUDEwXzEzICAgPSBEMjJfTjcyN19TNTA2LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGTDEzd19QMTJfMTMgICA9IEYyMl9ONzI3X1M1MDgsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENTMjNfUDVfMTMgICAgID0gRzIzX043MjhfUzUxMCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyM19QMTBfMTMgICAgPSBGMDRfTjcwNF9TNTA4LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUzIzX1AxMl8xMyAgICA9IEYwNl9ONzA2X1M1MDgsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENTMjJfUDVfMTkgICAgID0gRjA4X043MTBfUzUwOCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ1MyMl9QMTBfMTkgICAgPSBGMTBfTjcxMl9TNTA4LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDUzIyX1AxMl8xOSAgICA9IEYxMl9ONzE1X1M1MDgsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHcxM19GTF9QNV8xOSAgID0gRjE0X043MThfUzUwOCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdzEzX0ZMX1AxMF8xOSAgPSBGMTZfTjcyMF9TNTA4LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3MTNfRkxfUDEyXzE5ICA9IEYxOF9ONzIyX1M1MDgpCiMgCiMgCiMgdGVtcF9jb3VudHMgPC0gYmlnX2NvdW50c1ssMjo2MF1bLG9yZGVyKG1hdGNoKGNvbG5hbWVzKGJpZ19jb3VudHNbLDI6NjBdKSxyb3duYW1lcyhzYW1wbGVfdGFibGUpKSldCiMgYmlnX2NvdW50c1syOjYwXSA8LSBOVUxMCiMgYmlnX2NvdW50cyA8LSBjYmluZChiaWdfY291bnRzLHRlbXBfY291bnRzKQojIAojIHNhdmVSRFMoYmlnX2NvdW50cywiYmlnX2NvdW50cy5yZHMiKQoKYmlnX2NvdW50cyA8LSByZWFkUkRTKCdiaWdfY291bnRzLnJkcycpCgpjb3VudF9tYXRyaXggPC0gYXMubWF0cml4KGJpZ19jb3VudHNbLDI6bGVuZ3RoKGNvbG5hbWVzKGJpZ19jb3VudHMpKV0pCmNvbG5hbWVzKGNvdW50X21hdHJpeCkgPC0gcm93bmFtZXMoc2FtcGxlX3RhYmxlKQpyb3duYW1lcyhjb3VudF9tYXRyaXgpIDwtIGJpZ19jb3VudHMkZW5zZ2VuZQoKc2NlIDwtIFNpbmdsZUNlbGxFeHBlcmltZW50KGxpc3QoY291bnRzID0gY291bnRfbWF0cml4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBzYW1wbGVfdGFibGUpCnNjZSA8LSBzY2Vbcm93U3Vtcyhjb3VudHMoc2NlKSkgPiAgMCxdCnNjZSA8LSBjYWxjdWxhdGVRQ01ldHJpY3Moc2NlKQoKYGBgCgpgYGB7cn0KIyMgcHJlcGFyZSB0b3RhbCBjb3VudCBhbmQgdG90YWwgZmVhdHVyZXMgZGF0YQoKbXlfZGYgPC0gZGF0YS5mcmFtZSgic2FtcGxlX2lkIiA8LSBjb2xuYW1lcyhzY2UpLCAidG90YWxfY291bnRzIiA9IHNjZSR0b3RhbF9jb3VudHMsCiAgICAgICAgICAgICAgICAgICAgInRvdGFsX2ZlYXR1cmVzIiA9IHNjZSR0b3RhbF9mZWF0dXJlc19ieV9jb3VudHMsICJiYXRjaCIgPSBzY2UkYmF0Y2ggKQpnZ3Bsb3QobXlfZGYsYWVzKHRvdGFsX2NvdW50cywgZmlsbCA9IGJhdGNoKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNTApICsgCiAgdGhlbWVfbWluaW1hbCgpICsgZ2d0aXRsZSgiSGlzdG9ncmFtIG9mIHRvdGFsIGNvdW50cyIpICsgeWxhYigibnVtYmVyIG9mIHNhbXBsZXMiKSArIHhsYWIoInRvdGFsIGNvdW50cyIpCmBgYAoKYGBge3J9CgpnZ3Bsb3QobXlfZGYsYWVzKHRvdGFsX2ZlYXR1cmVzLCBmaWxsID0gYmF0Y2gpKSArIGdlb21faGlzdG9ncmFtKGJpbnMgPSA1MCkgKyAKICB0aGVtZV9taW5pbWFsKCkgKyBnZ3RpdGxlKCJIaXN0b2dyYW0gb2YgdG90YWwgZmVhdHVyZXMiKSArIHlsYWIoIm51bWJlciBvZiBzYW1wbGVzIikgKyB4bGFiKCJ0b3RhbCBmZWF0dXJlcyIpCgpgYGAKCgojIyNQQ0Egd2l0aG91dCBiYXRjaCBlZmZlY3QgcmVtb3ZhbAoKYGBge3J9CnNpemVGYWN0b3JzKHNjZSkgPC0gbGlicmFyeVNpemVGYWN0b3JzKHNjZSkKc2NlIDwtIG5vcm1hbGl6ZShzY2UpCgpzY2UgPC0gcnVuUENBKHNjZSkKCmRhdGEgPC0gcmVkdWNlZERpbShzY2UpCnBlcmNlbnRfdmFyX1BDMTwtIHBhc3RlKCJQQzEiLCBzcHJpbnRmKCcoJTAuMWYlJSBleHBsYWluZWQgdmFyLiknLCBhdHRyKGRhdGEsICdwZXJjZW50VmFyJylbMV0gKiAxMDAgKSkKcGVyY2VudF92YXJfUEMyPC0gcGFzdGUoIlBDMiIsIHNwcmludGYoJyglMC4xZiUlIGV4cGxhaW5lZCB2YXIuKScsIGF0dHIoZGF0YSwgJ3BlcmNlbnRWYXInKVsyXSAqIDEwMCApKQoKZGF0YSA8LSBkYXRhLmZyYW1lKGRhdGEpCmRhdGE8LWxlZnRfam9pbihyb3duYW1lc190b19jb2x1bW4oZGF0YSksIHJvd25hbWVzX3RvX2NvbHVtbihzYW1wbGVfdGFibGUpKQoKZ2dwbG90KGRhdGEsYWVzKFBDMSxQQzIsIGNvbG91ciA9IFBoZW5vdHlwZSwgc2hhcGUgPSBiYXRjaCApKSArIGdlb21fcG9pbnQoc2l6ZSA9IDMgKSArIAogIGdlb21fbGFiZWxfcmVwZWwoYWVzKGxhYmVsID0gcm93bmFtZSksIHNpemUgPSAyLGJveC5wYWRkaW5nICAgPSAwLjEscG9pbnQucGFkZGluZyA9IDAuMSwKICAgICAgICAgICAgICAgICAgIHNlZ21lbnQuY29sb3IgPSAnZ3JleTUwJykgKyB0aGVtZV9taW5pbWFsKCkgKyB4bGFiKHBlcmNlbnRfdmFyX1BDMSkgKyB5bGFiKHBlcmNlbnRfdmFyX1BDMikKCmBgYAoKCiMjI1BDQSB3aXRoIElMN1Igb25seQoKYGBge3J9CgpzY2UgPC0gc2NlWyxncmVwKCJJTDdSIiwgc2NlJFBoZW5vdHlwZSldCgpzY2UgPC0gcnVuUENBKHNjZSkKCmRhdGEgPC0gcmVkdWNlZERpbShzY2UpCnBlcmNlbnRfdmFyX1BDMTwtIHBhc3RlKCJQQzEiLCBzcHJpbnRmKCcoJTAuMWYlJSBleHBsYWluZWQgdmFyLiknLCBhdHRyKGRhdGEsICdwZXJjZW50VmFyJylbMV0gKiAxMDAgKSkKcGVyY2VudF92YXJfUEMyPC0gcGFzdGUoIlBDMiIsIHNwcmludGYoJyglMC4xZiUlIGV4cGxhaW5lZCB2YXIuKScsIGF0dHIoZGF0YSwgJ3BlcmNlbnRWYXInKVsyXSAqIDEwMCApKQoKZGF0YSA8LSBkYXRhLmZyYW1lKGRhdGEpCmRhdGE8LWxlZnRfam9pbihyb3duYW1lc190b19jb2x1bW4oZGF0YSksIHJvd25hbWVzX3RvX2NvbHVtbihzYW1wbGVfdGFibGUpKQoKZ2dwbG90KGRhdGEsYWVzKFBDMSxQQzIsIGNvbG91ciA9IHBvb2xzLCBzaGFwZSA9IGJhdGNoICkpICsgZ2VvbV9wb2ludChzaXplID0gMyApICsgCiAgZ2VvbV9sYWJlbF9yZXBlbChhZXMobGFiZWwgPSByb3duYW1lKSwgc2l6ZSA9IDIsYm94LnBhZGRpbmcgICA9IDAuMSxwb2ludC5wYWRkaW5nID0gMC4xLAogICAgICAgICAgICAgICAgICAgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnKSArIHRoZW1lX21pbmltYWwoKSArIHhsYWIocGVyY2VudF92YXJfUEMxKSArIHlsYWIocGVyY2VudF92YXJfUEMyKQoKYGBgCgojIyBERXNlcTIKCmBgYHtyfQpsaWJyYXJ5KERFU2VxMikKcm93bmFtZXMoYmlnX2NvdW50cykgPC0gYmlnX2NvdW50cyRlbnNnZW5lCmJpZ19jb3VudHMkZW5zZ2VuZSA8LSBOVUxMCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGJpZ19jb3VudHMsIGNvbERhdGEgPSBzYW1wbGVfdGFibGUsIGRlc2lnbiA9IH5QaGVub3R5cGUpCm15X3ZzdCA8LSB2c3QoZGRzKQoKcGNhRGF0YSA8LSBERVNlcTI6OnBsb3RQQ0EobXlfdnN0LCBpbnRncm91cCA9YygiUGhlbm90eXBlIiwiYmF0Y2giLCJzdGFnZSIsInBvb2xzIikscmV0dXJuRGF0YSA9IFRSVUUpCnBlcmNlbnRWYXIgPC0gcm91bmQoMTAwICogYXR0cihwY2FEYXRhLCAicGVyY2VudFZhciIpKQoKCmdncGxvdChwY2FEYXRhLGFlcyhQQzEsUEMyLGNvbG91ciA9IFBoZW5vdHlwZSwgc2hhcGUgPSBiYXRjaCkpICsgZ2VvbV9wb2ludChzaXplID0gMyApICsKICAgICAgICB4bGFiKHBhc3RlMCgiUEMxOiAiLHBlcmNlbnRWYXJbMV0sIiUgdmFyaWFuY2UiKSkgKwogICAgICAgIHlsYWIocGFzdGUwKCJQQzI6ICIscGVyY2VudFZhclsyXSwiJSB2YXJpYW5jZSIpKSArIAogICAgICAgICAgZ2VvbV9sYWJlbF9yZXBlbChhZXMobGFiZWwgPSBuYW1lKSwgc2l6ZSA9IDIsYm94LnBhZGRpbmcgICA9IDAuMSxwb2ludC5wYWRkaW5nID0gMC4xLAogICAgICAgICAgICAgICAgICAgc2VnbWVudC5jb2xvciA9ICdncmV5NTAnKSArCiAgICAgICAgdGhlbWVfbWluaW1hbCgpCgpgYGAKCiMjI0dlbmVzIGRyaXZpbmcgUEMxIGFuZCBQQzIKCmBgYHtyfQoKdG9wX2NvbnRyaWJzID0gZnVuY3Rpb24ob2JqZWN0KSB7CiAgIyBjYWxjdWxhdGUgdGhlIHZhcmlhbmNlIGZvciBlYWNoIGdlbmUKICBydiA8LSByb3dWYXJzKGFzc2F5KG9iamVjdCkpCgogICMgc2VsZWN0IHRoZSAxMDAwIHRvcCBnZW5lcyBieSB2YXJpYW5jZQogIHNlbGVjdCA8LSBvcmRlcihydiwgZGVjcmVhc2luZz1UUlVFKVtzZXFfbGVuKG1pbigxMDAwLCBsZW5ndGgocnYpKSldCgogICMgcGVyZm9ybSBhIFBDQSBvbiB0aGUgZGF0YSBpbiBhc3NheSh4KSBmb3IgdGhlIHNlbGVjdGVkIGdlbmVzCiAgcGNhIDwtIHByY29tcCh0KGFzc2F5KG9iamVjdClbc2VsZWN0LF0pKQoKICAjIHRoZSBjb250cmlidXRpb24gdG8gdGhlIHRvdGFsIHZhcmlhbmNlIGZvciBlYWNoIGNvbXBvbmVudAogIHBlcmNlbnRWYXIgPC0gcGNhJHNkZXZeMiAvIHN1bSggcGNhJHNkZXZeMiApCgogICMgVG9wIDIwIGNvbnRyaWJ1dGVycyB0byBQQzEgUEMyCiAgUENBMV9jb250cmliIDwtIHNvcnQoYWJzKHBjYSRyb3RhdGlvblssMV0pLCBkZWNyZWFzaW5nID0gVFJVRSApWzE6MjBdCiAgUENBMl9jb250cmliIDwtIHNvcnQoYWJzKHBjYSRyb3RhdGlvblssMl0pLCBkZWNyZWFzaW5nID0gVFJVRSApWzE6MjBdCiAgUENBX2NvbnRyaWIgPC0gYyhQQ0ExX2NvbnRyaWIsIFBDQTJfY29udHJpYikKICBQQ0FfY29udHJpYiA8LSBkYXRhLmZyYW1lKCJlbnNnZW5lIiA9IG5hbWVzKFBDQV9jb250cmliKSwgUENBX2NvbnRyaWIpCgoKCiAgUENBX2NvbnRyaWIgPC0gY2JpbmQoUENBX2NvbnRyaWIsIGRhdGEuZnJhbWUoIlBDIiA9IGMocmVwKCJQQzEiLDIwKSxyZXAoIlBDMiIsIjIwIikpKSkKICBQQ0FfY29udHJpYiA8LSBsZWZ0X2pvaW4oUENBX2NvbnRyaWIsIGdyY2gzOCwgYnkgPSAiZW5zZ2VuZSIpICU+JSBkcGx5cjo6c2VsZWN0KCJQQyIsInN5bWJvbCIsICJiaW90eXBlIikKICByZXR1cm4oUENBX2NvbnRyaWIpCn0KCmRhdGF0YWJsZSh0b3BfY29udHJpYnMobXlfdnN0KSkKCmBgYAoKCiMjI0RFU2VxIHdpdGggSUw3UiBvbmx5CgpgYGB7cn0KCmRkcyA8LSBkZHNbLGNvbERhdGEoZGRzKSRQQ0Ffb25seV9JTDdSID09ICJ5ZXMiXQoKCm15X3ZzdCA8LSB2c3QoZGRzKQoKcGNhRGF0YSA8LSBERVNlcTI6OnBsb3RQQ0EobXlfdnN0LCBpbnRncm91cCA9YygiUGhlbm90eXBlIiwiYmF0Y2giLCJzdGFnZSIsICJwb29scyIpLHJldHVybkRhdGEgPSBUUlVFKQpwZXJjZW50VmFyIDwtIHJvdW5kKDEwMCAqIGF0dHIocGNhRGF0YSwgInBlcmNlbnRWYXIiKSkKCgpnZ3Bsb3QocGNhRGF0YSxhZXMoUEMxLFBDMixjb2xvdXIgPSBwb29scywgc2hhcGUgPSBQaGVub3R5cGUgKSkgKyBnZW9tX3BvaW50KHNpemUgPSAzICkgKwogICAgICAgIHhsYWIocGFzdGUwKCJQQzE6ICIscGVyY2VudFZhclsxXSwiJSB2YXJpYW5jZSIpKSArCiAgICAgICAgeWxhYihwYXN0ZTAoIlBDMjogIixwZXJjZW50VmFyWzJdLCIlIHZhcmlhbmNlIikpICsgCiAgICAgICAgICAgICAgICAgIGdlb21fbGFiZWxfcmVwZWwoYWVzKGxhYmVsID0gbmFtZSksIHNpemUgPSAyLGJveC5wYWRkaW5nICAgPSAwLjEscG9pbnQucGFkZGluZyA9IDAuMSwKICAgICAgICAgICAgICAgICAgIHNlZ21lbnQuY29sb3IgPSAnZ3JleTUwJykgKwogICAgICAgdGhlbWVfbWluaW1hbCgpIAoKYGBgCgoKIyMjR2VuZXMgZHJpdmluZyBQQzEgYW5kIFBDMiAoSUw3IG9ubHkpCgpgYGB7cn0KZGF0YXRhYmxlKHRvcF9jb250cmlicyhteV92c3QpKQpgYGAKCgojRGlmZmVyZW50aWFsIEdlbmUgRXhwcmVzc2lvbgoKIyNJTDdSK0tJVCB3MTJfMTMgdiBCTQoKCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMSAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJXMTJfMTMiIHwgc2FtcGxlX3RhYmxlJHBvb2xzID09ICJCTSIpLCBdCgpydW5fZGVzZXEgPC0gZnVuY3Rpb24oY29sZGF0YSxjb250cmFzdDEpewpjb3VudHMgPC0gYmlnX2NvdW50c1ssY29sbmFtZXMoYmlnX2NvdW50cykgJWluJSByb3duYW1lcyhjb2xkYXRhKV0KZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnRzLCBjb2xEYXRhID0gY29sZGF0YSwgZGVzaWduID0gfmJhdGNoICsgcG9vbHMpCgpkZXNlcSA8LSBERVNlcShkZHMpCgpyZXMgPC0gcmVzdWx0cyhkZXNlcSwgY29udHJhc3QgPSBjKCJwb29scyIsIGNvbnRyYXN0MSwgIkJNIikpCnJlc09yZGVyZWQgPC0gcmVzW29yZGVyKHJlcyRwYWRqKSxdCnJlc09yZGVyZWQgPC0gZGF0YS5mcmFtZShyZXNPcmRlcmVkKQpyZXNPcmRlcmVkIDwtIGxlZnRfam9pbihyb3duYW1lc190b19jb2x1bW4ocmVzT3JkZXJlZCwgdmFyID0gImVuc2dlbmUiKSwgZ3JjaDM4LCBieSA9ICJlbnNnZW5lIikgJT4lIAogIGRwbHlyOjpzZWxlY3Qoc3ltYm9sLGxvZzJGb2xkQ2hhbmdlLHBhZGosYmlvdHlwZSkKZm9yX0RUIDwtIHJlc09yZGVyZWRbMTo1MDAsXQpyZXR1cm4obGlzdChyZXMgPSByZXNPcmRlcmVkLCBmb3JfRGF0YXRhYmxlID0gZm9yX0RUKSkKfQpteV9yZXMgPC0gcnVuX2Rlc2VxKGNvbGRhdGEsICJXMTJfMTMiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKCgpgYGB7cn0KCmhhbGxtYXJrIDwtIGdtdFBhdGh3YXlzKCJ+L2dlbm9tZV9hcHBzL0dTRUEvaC5hbGwudjYuMi5zeW1ib2xzLmdtdCIpCgpwbG90X2dzZWEgPC0gZnVuY3Rpb24ocmVzKXsKcmVzIDwtIHJlc1tjb21wbGV0ZS5jYXNlcyhyZXMpLF0KcmVzJGZjU2lnbiA8LSBzaWduKHJlcyRsb2cyRm9sZENoYW5nZSkKcmVzJGxvZ1AgPC0gLWxvZzEwKHJlcyRwYWRqKQpyZXMkbWV0cmljIDwtIHJlcyRsb2dQL3JlcyRmY1NpZ24KeTwtcmVzWyxjKCJzeW1ib2wiLCAibWV0cmljIildCmdlbmVMaXN0IDwtIHkkbWV0cmljCm5hbWVzKGdlbmVMaXN0KSA8LSB5JHN5bWJvbApnZW5lTGlzdCA8LSBnZW5lTGlzdFtvcmRlcihnZW5lTGlzdCwgZGVjcmVhc2luZyA9IFQpXQpmZ3NlYVJlcyA8LSBmZ3NlYShoYWxsbWFyaywgZ2VuZUxpc3QsIG5wZXJtPTEwMDAwLCBtYXhTaXplID0gNTAwKQpmZ3NlYVJlcyA8LSBmZ3NlYVJlc1tmZ3NlYVJlcyRwYWRqIDwgMC4wNSxdCnBsb3RHc2VhVGFibGUoaGFsbG1hcmtbZmdzZWFSZXMkcGF0aHdheV0sIGdlbmVMaXN0LCBmZ3NlYVJlcywgZ3NlYVBhcmFtID0gMC40KQp9CgpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgoKIyNJTDdSK0tJVCB3OF8xMCB2IEJNCgpgYGB7cn0KY29sZGF0YSA8LSBzYW1wbGVfdGFibGVbc2FtcGxlX3RhYmxlJGRpZmZfZ3JvdXBzID09IDEgJiAoIHNhbXBsZV90YWJsZSRwb29scyA9PSAiVzhfMTAiIHwgc2FtcGxlX3RhYmxlJHBvb2xzID09ICJCTSIpLCBdCgpteV9yZXMgPC0gcnVuX2Rlc2VxKGNvbGRhdGEsICJXOF8xMCIpCmRhdGF0YWJsZShteV9yZXMkZm9yX0RhdGF0YWJsZSkKYGBgCgoKCmBgYHtyfQpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgoKIyNJTDdSK0tJVCBDUzE5XzIzIHYgQk0KCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMSAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJDUzE5XzIzIiB8IHNhbXBsZV90YWJsZSRwb29scyA9PSAiQk0iKSwgXQoKbXlfcmVzIDwtIHJ1bl9kZXNlcShjb2xkYXRhLCJDUzE5XzIzIikKZGF0YXRhYmxlKG15X3JlcyRmb3JfRGF0YXRhYmxlKQpgYGAKCgoKYGBge3J9CnBsb3RfZ3NlYShteV9yZXMkcmVzKQpgYGAKCgojI0lMN1IrS0lUIENCIHYgQk0KCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMSAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJDQiIgfCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkJNIiksIF0KCm15X3JlcyA8LSBydW5fZGVzZXEoY29sZGF0YSwgIkNCIikKZGF0YXRhYmxlKG15X3JlcyRmb3JfRGF0YXRhYmxlKQpgYGAKCgoKYGBge3J9CnBsb3RfZ3NlYShteV9yZXMkcmVzKQpgYGAKCgojI0NEMzQrQ0QzOC1DRDQ1UkEtIHcxMl8xMyB2IEJNCgpgYGB7cn0KY29sZGF0YSA8LSBzYW1wbGVfdGFibGVbc2FtcGxlX3RhYmxlJGRpZmZfZ3JvdXBzID09IDIgJiAoIHNhbXBsZV90YWJsZSRwb29scyA9PSAiVzEyXzEzIiB8IHNhbXBsZV90YWJsZSRwb29scyA9PSAiQk0iKSwgXQoKbXlfcmVzIDwtIHJ1bl9kZXNlcShjb2xkYXRhLCAiVzEyXzEzIikKZGF0YXRhYmxlKG15X3JlcyRmb3JfRGF0YXRhYmxlKQpgYGAKCgoKYGBge3J9CnBsb3RfZ3NlYShteV9yZXMkcmVzKQpgYGAKCiMjQ0QzNCtDRDM4LUNENDVSQS0gdzhfMTAgdiBCTQoKCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMiAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJXOF8xMCIgfCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkJNIiksIF0KCm15X3JlcyA8LSBydW5fZGVzZXEoY29sZGF0YSwiVzhfMTAiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKCgpgYGB7cn0KcGxvdF9nc2VhKG15X3JlcyRyZXMpCmBgYAoKIyNDRDM0K0NEMzgtQ0Q0NVJBLSBDUzE5XzIzIHYgQk0KCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMiAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJDUzE5XzIzIiB8IHNhbXBsZV90YWJsZSRwb29scyA9PSAiQk0iKSwgXQoKbXlfcmVzIDwtIHJ1bl9kZXNlcShjb2xkYXRhLCAiQ1MxOV8yMyIpCmRhdGF0YWJsZShteV9yZXMkZm9yX0RhdGF0YWJsZSkKYGBgCgoKCmBgYHtyfQpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgojI0NEMzQrQ0QzOC1DRDQ1UkEtIENCIHYgQk0KCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMiAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJDQiIgfCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkJNIiksIF0KCm15X3JlcyA8LSBydW5fZGVzZXEoY29sZGF0YSwiQ0IiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKCmBgYHtyfQpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgojI0NEMzQrQ0QxOSsgdzEyXzEzIHYgQk0KCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMyAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJXMTJfMTMiIHwgc2FtcGxlX3RhYmxlJHBvb2xzID09ICJCTSIpLCBdCgpteV9yZXMgPC0gcnVuX2Rlc2VxKGNvbGRhdGEsICJXMTJfMTMiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKCmBgYHtyfQpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgojI0NEMzQrQ0QxOSsgdzhfMTAgdiBCTQoKCmBgYHtyfQpjb2xkYXRhIDwtIHNhbXBsZV90YWJsZVtzYW1wbGVfdGFibGUkZGlmZl9ncm91cHMgPT0gMyAmICggc2FtcGxlX3RhYmxlJHBvb2xzID09ICJXOF8xMCIgfCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkJNIiksIF0KCm15X3JlcyA8LSBydW5fZGVzZXEoY29sZGF0YSwiVzhfMTAiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKCmBgYHtyfQpwbG90X2dzZWEobXlfcmVzJHJlcykKYGBgCgoKIyNDRDM0K0NEMTkrIENTMTlfMjMgdiBCTQoKYGBge3J9CmNvbGRhdGEgPC0gc2FtcGxlX3RhYmxlW3NhbXBsZV90YWJsZSRkaWZmX2dyb3VwcyA9PSAzICYgKCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkNTMTlfMjMiIHwgc2FtcGxlX3RhYmxlJHBvb2xzID09ICJCTSIpLCBdCgpteV9yZXMgPC0gcnVuX2Rlc2VxKGNvbGRhdGEsIkNTMTlfMjMiKQpkYXRhdGFibGUobXlfcmVzJGZvcl9EYXRhdGFibGUpCmBgYAoKYGBge3J9CnBsb3RfZ3NlYShteV9yZXMkcmVzKQpgYGAKCgojI0NEMzQrQ0QxOSsgQ0IgdiBCTQoKYGBge3J9CmNvbGRhdGEgPC0gc2FtcGxlX3RhYmxlW3NhbXBsZV90YWJsZSRkaWZmX2dyb3VwcyA9PSAzICYgKCBzYW1wbGVfdGFibGUkcG9vbHMgPT0gIkNCIiB8IHNhbXBsZV90YWJsZSRwb29scyA9PSAiQk0iKSwgXQoKbXlfcmVzIDwtIHJ1bl9kZXNlcShjb2xkYXRhLCJDQiIpCmRhdGF0YWJsZShteV9yZXMkZm9yX0RhdGF0YWJsZSkKYGBgCgpgYGB7cn0KcGxvdF9nc2VhKG15X3JlcyRyZXMpCgpgYGAKCg==